using System;
using Castle.Windsor;
using CommonServiceLocator.WindsorAdapter;
using Microsoft.Practices.ServiceLocation;
using Sok.Munkae.Web.CastleWindsor;

namespace Sok.Munkae.Web
{
    public interface ISingletonInitializer
    {
        bool IsInitialized { get; }
        void Initialize();
        void Initialize(Action initializer);
        void InitializeOnce();
        void InitializeOnce(Action initializer);
        void InitializeOnce(Action initializer, Func<bool> initializationValidator);
        void InitializeOnce(Func<string> initializer, Func<bool> initializationValidator);
    }

    public class ServiceLocatorInitializer : SingletonInitializer<ServiceLocatorInitializer>
    {
        public string HostName { get; set; }
        public override void InitializeOnce(Func<string> initializer, 
                                           Func<bool> initializationValidator)
        {
            if(!IsInitialized)
            {
                HostName = initializer();
                IsInitialized = true;
            }
            if(!initializationValidator())
            {
                throw new InitializationException("Initialization is Invalid");
            }
        }
    }


    public abstract class SingletonInitializer<T> : ISingletonInitializer where T : new()
    {
        private static readonly object syncLock = new object();
        private static T _instance;

        protected SingletonInitializer()
        {}
        

        public static T Current()
        {
            if (_instance == null) {
                lock (syncLock) {
                    if (_instance == null) {
                        _instance = new T();
                    }
                }
            }

            return _instance;
        }
        
        public virtual bool IsInitialized { get; protected set; }
        public virtual void Initialize()
        {
            IsInitialized = true;
        }
        public virtual void Initialize(Action initializer)
        {
            initializer();
        }
        
        public virtual void InitializeOnce()
        {
            if(!IsInitialized)
            {
                Initialize();
                IsInitialized = true;
            }
        }
        public virtual void InitializeOnce(Action initializer)
        {
            if(!IsInitialized)
            {
                initializer();
                IsInitialized = true;
            }
        }

        public virtual void InitializeOnce(Action initializer, 
                                           Func<bool> initializationValidator)
        {
            if(!IsInitialized)
            {
                initializer();
                IsInitialized = true;
            }
            if(!initializationValidator())
            {
                throw new InitializationException("Initialization is Invalid");
            }
        }
        
        public virtual void InitializeOnce(Func<string> initializer, 
                                           Func<bool> initializationValidator)
        {
            if(!IsInitialized)
            {
                IsInitialized = true;
            }
            if(!initializationValidator())
            {
                throw new InitializationException("Initialization is Invalid");
            }
        }
        
    }
}